<template>
  <teleport to="body">
    <Transition name="command-palette" appear>
      <div v-if="isOpen" class="command-palette-overlay" @click="close">
        <div class="command-palette-container" @click.stop>
          <!-- 搜索框 -->
          <div class="command-palette-search">
            <el-icon class="search-icon"><Search /></el-icon>
            <input
              ref="searchInput"
              v-model="searchQuery"
              type="text"
              placeholder="搜索命令或输入..."
              class="command-input"
              @keydown="handleKeydown"
              @input="handleSearch"
            />
            <div class="command-shortcut">
              <kbd>ESC</kbd>
            </div>
          </div>

          <!-- 命令列表 -->
          <div class="command-palette-list" ref="commandList">
            <!-- 无结果 -->
            <div v-if="filteredCommands.length === 0" class="command-empty">
              <el-icon><DocumentRemove /></el-icon>
              <p>没有找到匹配的命令</p>
            </div>

            <!-- 命令分组 -->
            <div v-else class="command-groups">
              <div
                v-for="group in groupedCommands"
                :key="group.name"
                class="command-group"
              >
                <div v-if="group.commands.length > 0" class="group-title">
                  {{ group.name }}
                </div>
                <div
                  v-for="(command, index) in group.commands"
                  :key="command.id"
                  :class="[
                    'command-item',
                    { 'command-item--active': selectedIndex === getAbsoluteIndex(group, index) }
                  ]"
                  @click="executeCommand(command)"
                  @mouseenter="selectedIndex = getAbsoluteIndex(group, index)"
                  class="scale-in"
                >
                  <div class="command-icon">
                    <component :is="command.icon" />
                  </div>
                  <div class="command-content">
                    <div class="command-title">{{ command.title }}</div>
                    <div class="command-description">{{ command.description }}</div>
                  </div>
                  <div class="command-shortcut">
                    <kbd v-for="key in command.shortcut" :key="key">{{ key }}</kbd>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 底部提示 -->
          <div class="command-palette-footer">
            <div class="footer-tips">
              <span class="tip-item">
                <kbd>↑↓</kbd> 导航
              </span>
              <span class="tip-item">
                <kbd>Enter</kbd> 执行
              </span>
              <span class="tip-item">
                <kbd>ESC</kbd> 关闭
              </span>
            </div>
          </div>
        </div>
      </div>
    </Transition>
  </teleport>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
import { ElMessage } from 'element-plus'
import {
  Search,
  DocumentRemove,
  Plus,
  Clock,
  Setting,
  SwitchButton,
  Moon,
  Sunny,
  Monitor,
  Upload,
  TrendCharts,
  Document,
  QuestionFilled
} from '@element-plus/icons-vue'
import { useTheme } from '@/composables/useTheme'

// 类型定义
interface Command {
  id: string
  title: string
  description: string
  icon: any
  shortcut: string[]
  action: () => void
  category: string
  showInSearch?: boolean
}

interface CommandGroup {
  name: string
  commands: Command[]
}

// Props
interface Props {
  isOpen: boolean
}

const props = defineProps<Props>()
const emit = defineEmits<{
  close: []
}>()

// 响应式状态
const router = useRouter()
const store = useStore()
const { themeMode, toggleTheme } = useTheme()

const searchQuery = ref('')
const selectedIndex = ref(0)
const searchInput = ref<HTMLInputElement>()
const commandList = ref<HTMLElement>()

// 性能优化：防抖搜索
const debouncedSearchQuery = ref('')
let searchTimer: NodeJS.Timeout | null = null

// 性能优化：搜索结果缓存
const searchCache = new Map<string, Command[]>()
const lastSearchQuery = ref('')

// 命令定义
const commands = ref<Command[]>([
  // 页面导航
  {
    id: 'new-scoring',
    title: '开始评分',
    description: '创建新的内镜图像评分任务',
    icon: Plus,
    shortcut: ['N'],
    action: () => {
      router.push('/scoring/new')
      close()
    },
    category: 'navigation'
  },
  {
    id: 'scoring-history',
    title: '评分历史',
    description: '查看历史评分记录',
    icon: Clock,
    shortcut: ['H'],
    action: () => {
      router.push('/scoring/history')
      close()
    },
    category: 'navigation'
  },
  {
    id: 'settings',
    title: '系统设置',
    description: '打开系统设置页面',
    icon: Setting,
    shortcut: ['S'],
    action: () => {
      ElMessage.info('设置页面开发中...')
      close()
    },
    category: 'navigation'
  },
  {
    id: 'help',
    title: '帮助中心',
    description: '查看使用帮助和文档',
    icon: QuestionFilled,
    shortcut: ['?'],
    action: () => {
      ElMessage.info('帮助中心开发中...')
      close()
    },
    category: 'navigation'
  },

  // 主题切换
  {
    id: 'theme-light',
    title: '浅色模式',
    description: '切换到浅色主题',
    icon: Sunny,
    shortcut: ['L'],
    action: () => {
      toggleThemeToLight()
      close()
    },
    category: 'theme',
    showInSearch: themeMode.value !== 'light'
  },
  {
    id: 'theme-dark',
    title: '深色模式',
    description: '切换到深色主题',
    icon: Moon,
    shortcut: ['D'],
    action: () => {
      toggleThemeToDark()
      close()
    },
    category: 'theme',
    showInSearch: themeMode.value !== 'dark'
  },
  {
    id: 'theme-auto',
    title: '跟随系统',
    description: '主题跟随系统设置',
    icon: Monitor,
    shortcut: ['A'],
    action: () => {
      toggleThemeToAuto()
      close()
    },
    category: 'theme',
    showInSearch: themeMode.value !== 'auto'
  },

  // 快速操作
  {
    id: 'upload-image',
    title: '上传图像',
    description: '快速上传内镜图像',
    icon: Upload,
    shortcut: ['U'],
    action: () => {
      router.push('/scoring/new')
      close()
      // 可以触发文件选择器
    },
    category: 'actions'
  },
  {
    id: 'view-analytics',
    title: '数据分析',
    description: '查看评分数据分析',
    icon: TrendCharts,
    shortcut: ['A'],
    action: () => {
      ElMessage.info('数据分析功能开发中...')
      close()
    },
    category: 'actions'
  },
  {
    id: 'export-data',
    title: '导出数据',
    description: '导出评分数据',
    icon: Document,
    shortcut: ['E'],
    action: () => {
      ElMessage.info('数据导出功能开发中...')
      close()
    },
    category: 'actions'
  },
  {
    id: 'logout',
    title: '退出登录',
    description: '安全退出系统',
    icon: SwitchButton,
    shortcut: ['Q'],
    action: () => {
      handleLogout()
    },
    category: 'actions'
  }
])

// 性能优化：搜索函数
const performSearch = (query: string): Command[] => {
  // 检查缓存
  if (searchCache.has(query)) {
    return searchCache.get(query)!
  }

  // 执行搜索
  let result: Command[]
  if (!query) {
    result = commands.value.filter(cmd => cmd.showInSearch !== false)
  } else {
    const lowerQuery = query.toLowerCase()
    result = commands.value.filter(cmd => {
      const showInSearch = cmd.showInSearch !== false
      const matchesSearch =
        cmd.title.toLowerCase().includes(lowerQuery) ||
        cmd.description.toLowerCase().includes(lowerQuery) ||
        cmd.category.toLowerCase().includes(lowerQuery)
      return showInSearch && matchesSearch
    })
  }

  // 缓存结果
  searchCache.set(query, result)

  // 限制缓存大小
  if (searchCache.size > 50) {
    const firstKey = searchCache.keys().next().value
    searchCache.delete(firstKey)
  }

  return result
}

// 计算属性：使用防抖搜索查询
const filteredCommands = computed(() => {
  return performSearch(debouncedSearchQuery.value)
})

const groupedCommands = computed(() => {
  const groups: Record<string, Command[]> = {
    navigation: [],
    actions: [],
    theme: []
  }

  filteredCommands.value.forEach(command => {
    if (groups[command.category]) {
      groups[command.category].push(command)
    }
  })

  const groupNames = {
    navigation: '页面导航',
    actions: '快速操作',
    theme: '主题设置'
  }

  return Object.entries(groups)
    .filter(([_, commands]) => commands.length > 0)
    .map(([name, commands]) => ({
      name: groupNames[name as keyof typeof groupNames] || name,
      commands
    }))
})

// 方法
const close = () => {
  emit('close')
  searchQuery.value = ''
  debouncedSearchQuery.value = ''
  selectedIndex.value = 0

  // 清理防抖定时器
  if (searchTimer) {
    clearTimeout(searchTimer)
    searchTimer = null
  }
}

const open = () => {
  nextTick(() => {
    searchInput.value?.focus()
  })
}

const getAbsoluteIndex = (group: CommandGroup, index: number): number => {
  let absoluteIndex = 0
  for (const g of groupedCommands.value) {
    if (g === group) {
      return absoluteIndex + index
    }
    absoluteIndex += g.commands.length
  }
  return 0
}

const executeCommand = (command: Command) => {
  command.action()
}

const toggleThemeToLight = () => {
  const { setTheme } = useTheme()
  setTheme('light')
  ElMessage.success('已切换到浅色模式')
}

const toggleThemeToDark = () => {
  const { setTheme } = useTheme()
  setTheme('dark')
  ElMessage.success('已切换到深色模式')
}

const toggleThemeToAuto = () => {
  const { setTheme } = useTheme()
  setTheme('auto')
  ElMessage.success('已切换到跟随系统')
}

const handleLogout = async () => {
  try {
    await store.dispatch('auth/logout')
    ElMessage.success('退出登录成功')
    router.push('/login')
    close()
  } catch (error) {
    ElMessage.error('退出登录失败')
  }
}

const handleKeydown = (event: KeyboardEvent) => {
  switch (event.key) {
    case 'Escape':
      event.preventDefault()
      close()
      break
    case 'ArrowUp':
      event.preventDefault()
      navigateUp()
      break
    case 'ArrowDown':
      event.preventDefault()
      navigateDown()
      break
    case 'Enter':
      event.preventDefault()
      executeSelectedCommand()
      break
    case 'n':
    case 'N':
      if (!searchQuery.value) {
        event.preventDefault()
        commands.value.find(cmd => cmd.id === 'new-scoring')?.action()
      }
      break
    case 'h':
    case 'H':
      if (!searchQuery.value) {
        event.preventDefault()
        commands.value.find(cmd => cmd.id === 'scoring-history')?.action()
      }
      break
    case 'l':
    case 'L':
      if (!searchQuery.value) {
        event.preventDefault()
        commands.value.find(cmd => cmd.id === 'theme-light')?.action()
      }
      break
    case 'd':
    case 'D':
      if (!searchQuery.value) {
        event.preventDefault()
        commands.value.find(cmd => cmd.id === 'theme-dark')?.action()
      }
      break
    case 'a':
    case 'A':
      if (!searchQuery.value) {
        event.preventDefault()
        commands.value.find(cmd => cmd.id === 'theme-auto')?.action()
      }
      break
    case 'q':
    case 'Q':
      if (!searchQuery.value) {
        event.preventDefault()
        commands.value.find(cmd => cmd.id === 'logout')?.action()
      }
      break
  }
}

const handleSearch = () => {
  // 防抖搜索：立即搜索前3个字符，之后防抖200ms
  const query = searchQuery.value

  if (query.length <= 3) {
    // 立即搜索短查询
    debouncedSearchQuery.value = query
    selectedIndex.value = 0
  } else {
    // 长查询使用防抖
    if (searchTimer) {
      clearTimeout(searchTimer)
    }

    searchTimer = setTimeout(() => {
      debouncedSearchQuery.value = query
      selectedIndex.value = 0
    }, 200)
  }
}

const navigateUp = () => {
  const totalItems = filteredCommands.value.length
  if (totalItems === 0) return

  selectedIndex.value = selectedIndex.value <= 0
    ? totalItems - 1
    : selectedIndex.value - 1

  scrollToActiveCommand()
}

const navigateDown = () => {
  const totalItems = filteredCommands.value.length
  if (totalItems === 0) return

  selectedIndex.value = selectedIndex.value >= totalItems - 1
    ? 0
    : selectedIndex.value + 1

  scrollToActiveCommand()
}

const executeSelectedCommand = () => {
  const totalItems = filteredCommands.value.length
  if (totalItems === 0) return

  let currentIndex = 0
  for (const group of groupedCommands.value) {
    for (const command of group.commands) {
      if (currentIndex === selectedIndex.value) {
        executeCommand(command)
        return
      }
      currentIndex++
    }
  }
}

const scrollToActiveCommand = () => {
  nextTick(() => {
    const activeElement = commandList.value?.querySelector('.command-item--active')
    if (activeElement) {
      activeElement.scrollIntoView({
        block: 'nearest',
        behavior: 'smooth'
      })
    }
  })
}

// 监听开关状态
watch(() => props.isOpen, (isOpen) => {
  if (isOpen) {
    open()
  }
})

// 全局键盘快捷键
const handleGlobalKeydown = (event: KeyboardEvent) => {
  // Cmd/Ctrl + K
  if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
    event.preventDefault()
    if (!props.isOpen) {
      // 需要从父组件打开
      return
    }
  }
}

onMounted(() => {
  document.addEventListener('keydown', handleGlobalKeydown)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleGlobalKeydown)
})
</script>

<style scoped>
/* ===== 命令面板遮罩层 ===== */
.command-palette-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

/* ===== 命令面板容器 ===== */
.command-palette-container {
  background-color: var(--uc-bg-secondary);
  border: 1px solid var(--uc-border-primary);
  border-radius: 16px;
  box-shadow: var(--uc-shadow-lg);
  width: 100%;
  max-width: 640px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ===== 搜索框 ===== */
.command-palette-search {
  display: flex;
  align-items: center;
  padding: 1rem 1.5rem;
  border-bottom: 1px solid var(--uc-border-primary);
  gap: 1rem;
}

.search-icon {
  color: var(--uc-text-tertiary);
  font-size: 1.25rem;
  flex-shrink: 0;
}

.command-input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--uc-text-primary);
  font-family: var(--uc-font-family);
}

.command-input::placeholder {
  color: var(--uc-text-tertiary);
}

.command-shortcut {
  display: flex;
  gap: 0.25rem;
}

kbd {
  background-color: var(--uc-bg-tertiary);
  border: 1px solid var(--uc-border-primary);
  border-radius: 6px;
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--uc-text-secondary);
  font-family: var(--uc-font-family-mono);
  font-variant-numeric: tabular-nums;
}

/* ===== 命令列表 ===== */
.command-palette-list {
  flex: 1;
  overflow-y: auto;
  padding: 0.5rem 0;
}

.command-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 3rem 1.5rem;
  color: var(--uc-text-tertiary);
  text-align: center;
}

.command-empty .el-icon {
  font-size: 2.5rem;
  margin-bottom: 1rem;
  opacity: 0.5;
}

.command-empty p {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 500;
}

/* ===== 命令分组 ===== */
.command-groups {
  display: flex;
  flex-direction: column;
}

.command-group {
  margin-bottom: 0.5rem;
}

.group-title {
  padding: 0.5rem 1.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--uc-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  user-select: none;
}

/* ===== 命令项 ===== */
.command-item {
  display: flex;
  align-items: center;
  padding: 0.75rem 1.5rem;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  border: 2px solid transparent;
  margin: 0 0.75rem;
  border-radius: 12px;
  gap: 1rem;
}

.command-item:hover {
  background-color: var(--uc-bg-tertiary);
}

.command-item--active {
  background-color: var(--uc-accent-primary);
  color: white;
}

.command-item--active .command-icon,
.command-item--active .command-title,
.command-item--active .command-description {
  color: white;
}

.command-icon {
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--uc-bg-tertiary);
  border-radius: 8px;
  color: var(--uc-text-secondary);
  font-size: 1rem;
  flex-shrink: 0;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.command-item--active .command-icon {
  background-color: rgba(255, 255, 255, 0.2);
  color: white;
}

.command-content {
  flex: 1;
  min-width: 0;
}

.command-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--uc-text-primary);
  margin-bottom: 0.125rem;
  font-family: var(--uc-font-family);
}

.command-description {
  font-size: 0.75rem;
  color: var(--uc-text-tertiary);
  line-height: 1.4;
  font-family: var(--uc-font-family);
}

.command-item--active .command-description {
  color: rgba(255, 255, 255, 0.8);
}

/* ===== 底部提示 ===== */
.command-palette-footer {
  padding: 0.75rem 1.5rem;
  border-top: 1px solid var(--uc-border-primary);
  background-color: var(--uc-bg-tertiary);
}

.footer-tips {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: center;
}

.tip-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.75rem;
  color: var(--uc-text-tertiary);
  font-family: var(--uc-font-family);
}

/* ===== 过渡动画 ===== */
.command-palette-enter-active,
.command-palette-leave-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.command-palette-enter-from,
.command-palette-leave-to {
  opacity: 0;
}

.command-palette-enter-from .command-palette-container,
.command-palette-leave-to .command-palette-container {
  transform: scale(0.9) translateY(1rem);
  opacity: 0;
}

/* ===== 响应式设计 ===== */
@media (max-width: 640px) {
  .command-palette-overlay {
    padding: 1rem;
  }

  .command-palette-container {
    max-height: 90vh;
  }

  .command-palette-search {
    padding: 0.75rem 1rem;
  }

  .command-input {
    font-size: 1rem;
  }

  .command-item {
    padding: 0.625rem 1rem;
    margin: 0 0.5rem;
  }

  .command-icon {
    width: 1.75rem;
    height: 1.75rem;
    font-size: 0.875rem;
  }

  .group-title {
    padding: 0.5rem 1rem;
  }

  .command-palette-footer {
    padding: 0.5rem 1rem;
  }

  .footer-tips {
    gap: 0.75rem;
    flex-wrap: wrap;
  }

  .tip-item {
    font-size: 0.7rem;
  }
}

/* ===== 深色模式适配 ===== */
@media (prefers-color-scheme: dark) {
  .command-palette-overlay {
    background-color: rgba(0, 0, 0, 0.6);
  }
}

/* ===== 高对比度模式 ===== */
@media (prefers-contrast: high) {
  .command-palette-container {
    border: 2px solid var(--uc-text-primary);
  }

  .command-item--active {
    border-color: var(--uc-accent-primary);
  }
}

/* ===== 减少动画偏好 ===== */
@media (prefers-reduced-motion: reduce) {
  .command-palette-enter-active,
  .command-palette-leave-active {
    transition: none;
  }

  .command-item {
    transition: none;
  }

  .command-item:hover {
    transform: none;
  }
}

/* ===== 滚动条样式 ===== */
.command-palette-list::-webkit-scrollbar {
  width: 6px;
}

.command-palette-list::-webkit-scrollbar-track {
  background: transparent;
}

.command-palette-list::-webkit-scrollbar-thumb {
  background-color: var(--uc-border-primary);
  border-radius: 3px;
}

.command-palette-list::-webkit-scrollbar-thumb:hover {
  background-color: var(--uc-border-secondary);
}
</style>